/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 */

package com.huawei.hms.audioeditor.demo.util;

import android.content.Context;
import android.text.TextUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;

import com.huawei.hms.audioeditor.sdk.util.SmartLog;

/**
 * Tool class for obtaining the file path
 *
 * @since 2021-05-10
 */
public class FileUtils {
    private static final String TAG = "FileUtils";

    /**
     * Writes data stream to the file.
     * @param buffer Cache to be written
     * @param strFilePath Destination Save File Address
     * @param append Indicates whether to write in append mode.
     */
    public static void writeBufferToFile(byte[] buffer, String strFilePath, boolean append) {
        File file = new File(strFilePath);
        RandomAccessFile randomAccessFile = null;
        FileOutputStream fileOutputStream = null;
        try {
            if (append) {
                // Appending write mode.
                randomAccessFile = new RandomAccessFile(file, "rw");
                randomAccessFile.seek(file.length());
                randomAccessFile.write(buffer);
            } else {
                // Overwrite mode.
                fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write(buffer);
                fileOutputStream.flush();
            }
        } catch (IOException e) {
            SmartLog.e(TAG, e.getMessage());
        } finally {
            try {
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                SmartLog.e("Failed to close stream.", e.getMessage());
            }
        }
    }

    /**
     * Create a directory to store the voice files generated by the AiDubbing.
     * @param context context
     * @return file path
     */
    public static String initFile(Context context) {
        String filePath = context.getExternalFilesDir("wav").getPath();
        File file = new File(filePath);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                SmartLog.i(TAG, "mkdirs failed");
            }
            SmartLog.i("initFile", "Create a directory to store the voice files generated by the AIDubbing.");
        }
        return filePath;
    }

    /**
     * Delete a file.
     * @param filePath File path
     */
    public static void deleteFile(String filePath) {
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        deleteFile(new File(filePath));
    }

    /**
     * Delete all contents of the folder
     * @param file File
     */
    public static void deleteFile(File file) {
        if (file != null && file.exists()) { // Check whether the file exists.
            if (file.isDirectory()) { // Otherwise if it's a directory
                File[] files = file.listFiles(); // Declares all files in the directory. files[];
                if (files != null) {
                    for (File childFile : files) { // Traverse all files in the directory.
                        deleteFile(childFile); // Use this method to iterate each file.
                    }
                }
            }

            // Safely delete files
            deleteFileSafely(file);
        }
    }

    /**
     * Safely delete files. Prevents the system from reporting an error when a file is re-created after being deleted. open failed: EBUSY (Device or resource busy)
     * @param file file
     * @return true  false
     */
    public static boolean deleteFileSafely(File file) {
        if (file != null) {
            String tmpPath = file.getParent() + File.separator + System.currentTimeMillis();
            File tmp = new File(tmpPath);
            boolean renameTo = file.renameTo(tmp);
            if (!renameTo) {
                SmartLog.e(TAG, "deleteFileSafely file.renameTo fail!");
            }
            return tmp.delete();
        }
        return false;
    }
}
